import axios, { AxiosRequestConfig, InternalAxiosRequestConfig, AxiosInstance, AxiosResponse, AxiosRequestHeaders } from 'axios';
import qs from 'qs';
import { Message } from '@arco-design/web-vue';
import router from '@/router'
import { isLoadingStore } from "@/store/login";
const store = isLoadingStore()

const axiosInstance: AxiosInstance = axios.create({
    // baseURL: '/api',
    baseURL: import.meta.env.VITE_BASE_URL as string,
    timeout: 5000,
});
let requestList = [];
const setLoadingToFalse = response => {
    requestList
        .filter(item => item.url == response.config.url && item.method == response.config.method)
        .forEach(item => (item.isLoading = false));
    //所有请求都加载完才让加载提示消失
    if (requestList.every(item => !item.isLoading)) store.changeIsLoading(false);
};
// 添加请求拦截器
axiosInstance.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        // 在发送请求之前做些什么
        // return config;
        const { method } = config


        const headers: AxiosRequestHeaders = config.headers ?? {}
        // config.headers = {
        //     'X-Requested-With': 'XMLHttpRequest',
        //     'Content-Type': 'application/json'
        // };

        const token = localStorage.getItem('accessToken');
        // console.log(config);
        
        if (method === 'get' || method === 'delete') {
            headers['Cache-Control'] = 'no-cache'
            headers['Content-type'] = 'application/x-www-form-urlencoded'
        } else if (method === 'post' || method === 'put') {
            // console.log(headers);
            if (headers.enctype) {
                headers['Content-type'] = headers.enctype
                
            } else {
                headers['Content-type'] = 'application/json'
            }
            // headers['Content-type'] = 'application/json'
            // headers['Content-type'] = 'multipart/form-data'
            // headers['Content-type'] = 'application/x-www-form-urlencoded'
        }
        if (typeof headers['Content-type'] === 'string' && headers['Content-type'].includes('application/x-www-form-urlencoded')) {
            config.data = qs.stringify(config.data)
        }

        if (token) {
            //  config.params = {'token':token} //如果要求携带在参数中
            //  config.headers.Authorization = token; //如果要求携带在请求头中
            headers['etoken'] = token;
            // headers['Authorization']=token
        } else {
            router.push({
                // path: '/login',
                name: 'Login',
            })
        }

        // 在发送请求之前做些什么
        return {
            ...config,
            headers
        }
    },
    (error: any) => {
        // 处理请求错误
        return Promise.reject(error);
    },
);

// 添加响应拦截器
axiosInstance.interceptors.response.use(
    (response: AxiosResponse) => {
        // 对响应数据做点什么
        // return response;
        // console.log(response);
        const responseStatus = response.status || response.statusCode
        if (responseStatus === 200) {
            // 如果存在token信息，刷新状态以及缓存
            if (response.data?.data?.accessToken && response.data?.data?.refreshToken) {
                // 响应数据中存在AccessToken
                localStorage.setItem('accessToken', response.data.data.accessToken)
            }
            if (response.data?.code === 2007) {
                Message.error({
                    content: response.data?.message,
                    position: 'top',
                });
            }

            return response.data
        }
        else if (responseStatus === 401) {
            //3002 TOKEN过期  3003 TOKEN不合法
            if ([2001, 3002, 3003].includes(response.data.code)) {
                router.push({
                    // path: '/login',
                    name: 'Login',
                })
                localStorage.removeItem('accessToken')
            }
            return response.data
        }
        setLoadingToFalse(response);
        return response.data
    },
    (error: any) => {
        // 处理响应错误
        // return Promise.reject(error);
        // console.log(error);
        const responseStatus = error.response?.status || error.response?.statusCode
        if (responseStatus === 401) {
            //3002 TOKEN过期  3003 TOKEN不合法
            if ([2001, 3002, 3003].includes(error.response.data.code)) {
                router.push({
                    // path: '/login',
                    name: 'Login',
                })
                localStorage.removeItem('accessToken')
            }
            return error.response.data
        }
        setLoadingToFalse(error);

        return Promise.reject(error.response?.data);
    },
);
/**
 * 响应体封装
 */
export interface IResponseData<T> {
    success: boolean
    code: number
    msg?: string
    data?: T | null
}
const httpPack = {
    get: <P, R>(url: string, param?: P, config?: AxiosRequestConfig): Promise<IResponseData<R>> => httpNative.get<P, IResponseData<R>>(url, param, config),
    delete: <P, R>(url: string, param?: P, config?: AxiosRequestConfig): Promise<IResponseData<R>> => httpNative.delete<P, IResponseData<R>>(url, param, config),
    post: <P, R>(url: string, data?: P, config?: AxiosRequestConfig): Promise<IResponseData<R>> => httpNative.post<P, IResponseData<R>>(url, data, config),
    put: <P, R>(url: string, data?: P, config?: AxiosRequestConfig): Promise<IResponseData<R>> => httpNative.put<P, IResponseData<R>>(url, data, config)
}

const httpNative = {
    get: <P, R>(url: string, param?: P, config?: AxiosRequestConfig): Promise<R> => new Promise<R>((resolve, reject) => {
        const paramStr = qs.stringify(param)
        axiosInstance.get(`${url}?${paramStr}`, config).then((res) => {
            !res.data && reject(res)
            res.data.success ? resolve(res.data as R) : reject(res.data as R)
        }).catch(err => reject(err))
    }),
    delete: <P, R>(url: string, param?: P, config?: AxiosRequestConfig): Promise<R> => new Promise<R>((resolve, reject) => {
        const paramStr = qs.stringify(param)
        axiosInstance.delete(`${url}?${paramStr}`, config).then((res) => {
            !res.data && reject(res)
            res.data.success ? resolve(res.data as R) : reject(res.data as R)
        }).catch(err => reject(err))
    }),
    post: <P, R>(url: string, data?: P, config?: AxiosRequestConfig): Promise<R> => new Promise<R>((resolve, reject) => {
        axiosInstance.post(url, data, config).then((res) => {
            !res.data && reject(res)
            res.data.success ? resolve(res.data as R) : reject(res.data as R)
        }).catch(err => reject(err))
    }),
    put: <P, R>(url: string, data?: P, config?: AxiosRequestConfig): Promise<R> => new Promise<R>((resolve, reject) => {
        axiosInstance.put(url, data, config).then((res) => {
            !res.data && reject(res)
            res.data.success ? resolve(res.data as R) : reject(res.data as R)
        }).catch(err => reject(err))
    })
}

/**
 * 包装响应体后的http请求
 */
export const http = httpPack
/**
 * 原生不包装的http请求
 */
export const httpNa = httpNative
